/*
 * @Descripttion:  纯手写
 * @version: 
 * @Author: Zuo
 * @Date: 2021-08-03 17:20:22
 * @LastEditors: Zuo
 * @LastEditTime: 2021-08-04 14:29:32
 */
(function(window){
    function Promise(excutor){
        const self = this;
        self.data = undefined;
        self.status = 'pending';
        self.callbacks = [];
   
        function resolve(value){
            if(self.status !== 'pending'){
                return;
            }
            
            self.data = value;
            self.status = 'resolved'
            if(self.callbacks.length>0){
                setTimeout(()=>{
                    self.callbacks.forEach((objs)=>{
                            objs.onResolved(value);
                    })
                })
            }
        }

        function reject(reason){
            if(self.status !== 'pending'){
                return;
            }
            
            self.data = reason;
            self.status = 'rejected'
            if(self.callbacks.length>0){
                setTimeout(()=>{
                    self.callbacks.forEach((objs)=>{
                            objs.onRejected(reason);
                    })
                })
            }
        }
      
        try{
            excutor(resolve,reject)
        }catch(error){
            reject(error)
        }
    }

    Promise.prototype.then = function(onResolved,onRejected){
         onResolved = typeof onResolved === 'function' ? onResolved : (value) => value
         onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {throw reason}
        const self = this;
        return new Promise((resolve,reject)=>{
            function handler(callback){
                try{
                    const result = callback(self.data);
                    if(result instanceof Promise){
                        result.then(resolve,reject);
                    }else{
                        resolve(result);
                    }
                }catch(error){
                    reject(error);
                }
            }
            if(self.status == 'pending'){
                self.callbacks.push({
                    onResolved(){
                        handler(onResolved)
                    },
                    onRejected(){
                        handler(onRejected)
                    },
                })
            }else if(self.status == 'resolved'){
                setTimeout(()=>{
                    handler(onResolved);
                })
            }else{
                setTimeout(()=>{
                    handler(onRejected);
                })
            }
        })
        

    }

    Promise.prototype.catch = function(onRejected){
        return this.then(undefined,onRejected)
    }

    Promise.reject = function(reason){
        return new Promise((_,reject)=>{
            reject(reason)
        })
    }

    Promise.resolve = function(value){
        return new Promise((resolve,reject)=>{
            if(value instanceof Promise){
                value.then(resolve,reject)
            }else{
                resolve(value)
            }
        })
        
    }
    // all 全部成功 返回原数组的顺序结果的promise。 有一个失败就直接返回失败的promise
    Promise.all = function(promises){
        let values = new Array(promises.length);
        let count = 0;
      return  new Promise((resolve,reject)=>{
            promises.forEach((p,index)=>{
               Promise.resolve(p).then(
                    value =>{
                      count++
                      values[index] = value
                      if(count == promises.length){
                        resolve(values);
                      }
                    },
                    reject
                )
            })
        })
    }

    // race 返回第一个完成的promise的结果
    Promise.race = function(promises){
        return  new Promise((resolve,reject)=>{
            promises.forEach((p)=>{
                // p 可能不是一个promise，需要用Promise.reslove（p） 包装一下 变成一个promise对象。 不影响其原本的值
                Promise.resolve(p).then(value=>{ // 有一个成功  就return 一个成功
                    resolve(value) 
                },
                reason =>{  //有一个失败 就return 一个失败
                    reject(reason)
                }
                )
            })
        })
    }

    window.Promise = Promise;


})(window)